//-----------------------------------------------------------------------------
// Filename: Authenticator.cs
//
// Description: 
// Implements a factory design for instantiating objects to perform authentication.
// 
// History:
// 11 Dec 2004	Aaron Clauson	Created.
// 18 Dec 2004  Aaron Clauson	Added GetPassword and SetTimeout methods to AuthenticatorProduct.
//
// License: Public Domain.
//-----------------------------------------------------------------------------

using System;
using System.Xml;
using MaverickLite.Config;
using BlueFace.Sys;
using log4net;

namespace MaverickLite.Security
{
	public enum AuthenticatorTypesEnum
	{
		File = 0,
		Database = 1,
	}

	public class AuthenticatorTypes
	{
		public static AuthenticatorTypesEnum GetAuthenticatorType(string authenticatorTypeName)
		{
			return (AuthenticatorTypesEnum)Enum.Parse(typeof(AuthenticatorTypesEnum), authenticatorTypeName, true);
		}
	}
	
	public struct AuthenticationResult
	{
		public bool Authenticated;
		public string View;
		public string ErrorMessage;
		public Credentials AuthenticatedCredentials;

		public AuthenticationResult(bool authenticated, string view)
		{
			Authenticated = authenticated;
			View = view;
			ErrorMessage = null;
			AuthenticatedCredentials = null;
		}
	}

	/// <summary>
	///
	/// </summary>
	public abstract class AuthenticatorProduct
	{
		public const string TIMESTAMP_FORMAT = "r";					// String format to store timestamps in.
		public const int AUTHENTICATION_SESSION_TIMEOUT = 30;		// Number of minutes before the authentication cookie will timeout.
		
		protected TimeSpan m_sessionDuration = new TimeSpan(0, AUTHENTICATION_SESSION_TIMEOUT, 0);	// The default duration that authenticated sessions will be valid for. 

		public abstract bool Authenticate(Credentials credentials, string ipAddress);
		public abstract bool Authenticate(string authenticationId);
		public abstract string GetUsernameForSessionId(string authenticationSessionId);
		public abstract bool Authenticate(string username, string password);
		public abstract void CreateSession(string username, string authenticationId, string ipAddress);
		public abstract void RemoveSession(string session);
		public abstract void RemoveSession(Credentials requestCredentials);
		public abstract void UpdateSessionContactTime(string sessionId);
		public abstract string AuthenticateWebRequest(Credentials requestCredentials, string ipAddress);
		public abstract DateTime GetSessionTimeout(string sessionId);
		//public abstract void GetPassword(string account, out string emailaddress, out string username, out string password);
		public abstract void SetTimeout(TimeSpan duration);
	}

	public class AuthenticatorFactory
	{
		private ILog logger = MavAppState.logger;

		public AuthenticatorProduct CreateAuthenticator(AuthenticatorTypesEnum authType, string authXMLNode)
		{
			//logger.Debug("AuthenticatorFactory creating authenticator for " + authType.ToString() + " and " + parameter + ".");
			
			AuthenticatorProduct authenticator = null;
			XmlDocument xmlAuthDom = new XmlDocument();
			xmlAuthDom.LoadXml(authXMLNode);
            
			switch(authType)
			{
				case AuthenticatorTypesEnum.File:
					string filePath = xmlAuthDom.DocumentElement.SelectSingleNode("filepath").InnerText;
					authenticator = new FileAuthenticator(filePath);

					break;

				case AuthenticatorTypesEnum.Database:
					DBAuthenticationStore dbAuthStore = new DBAuthenticationStore(authXMLNode);
					authenticator = new DBAuthenticator(dbAuthStore);

					break;

				default:
					throw new ApplicationException("The Authenticator type requested could not be created.");
			}
			
			return authenticator;
		}
	}
}
